/********************************************************
 *
 *         Copyright (C), 1994  SEIKO EPSON Corp.
 *         ALL RIGHTS RESERVED                  
 *                                            
 *  	file name : time.c
 *
 *	This include time functions
 *	time(), gmtime(), mktime().
 *	No support for local time functionality.
 *
 *  	Revision history 
 *      	94/2/7    	first release for 88	M.Kudo
 *		97/3/25		modify for 33		M.Kudo
 *
 *
 ********************************************************/

#include "time.h"
#include "_mj_os.h"

extern time_t gm_sec;		/* hold sec from 1970.1.1 */

/*
 * In mj6000, time is calculated from 1904-1-1
 * But in ansi c, time is calculated from 1970-1-1
 */
DateTimeType dt = {
	(unsigned char)0,
	(unsigned char)0,
	(unsigned char)0,
	(unsigned char)1,
	(unsigned char)1,
	(unsigned short)(1970u),
	(unsigned char)4 
};
#define get_os_time_base_seconds()	((time_t)(TimDateTimeToSeconds(&dt)))

/**************************************************
 *		time_t time(t)
 *
 *	return sec from 1970.1.1
 *	and set to *t also	
 *	
 **************************************************/

time_t time(time_t *t)		// implemented in mj6000
{
	time_t curr = (time_t)(TimGetSeconds() - get_os_time_base_seconds());
	if (t != NULL) {
		*t = curr;
	}
	return curr;
}

/**************************************************
 *		long year2day(year)
 *
 *	convert year(0 is 1900) to day(day from 1970.1.1)
 *	year >= 70
 *	
 **************************************************/

static long year2day(int year)
{
	long day;
	int lyear;

	lyear = (year-1)/4-17;		/* calc leap year */
	day = (year-70)*365+lyear;	/* calc days */
	return(day);
}

/**************************************************
 *		long mon2day(year,month)
 *
 *	convert month to day (year.0 to year.month)
 *	year >= 70, 0 <= month <= 13
 *	
 **************************************************/

static long mon2day(int year, int month)
{
	static const int lyear_mon[] =		/* for leap year */
		{0,31,60,91,121,152,182,213,244,274,305,335,366};
	static const int year_mon[] =		/* for non leap year */
		{0,31,59,90,120,151,181,212,243,273,304,334,365};

	long day;
	
	if ((year & 3) == 0)			/* get lower 2 bit */
		day = lyear_mon[month];
	else
		day = year_mon[month];
	return(day);				/* return day */
}

/**************************************************
 *		time_t mktime(t)
 *
 *	from struct tm *t, make	time_t
 *	every member in struct tm *t should be in correct range
 *	like as "seconds (0-59)"
 *	
 **************************************************/

time_t mktime(struct tm *t)		// keep
{
	time_t sec;
	long day,day0;

	day0 = mon2day(t->tm_year,t->tm_mon);	/* calc day of year */
	day = year2day(t->tm_year) + day0 + t->tm_mday -1;	/* calc days */
	sec = day*86400 + (long)t->tm_hour*3600 
		+ t->tm_min*60 + t->tm_sec;	/* calc sec */
	t->tm_wday = (day+4)%7;			/* calc day of week */
	t->tm_yday = day0+t->tm_mday-1;		/* set day of year */
	return(sec);				/* return second */
}

/**************************************************
 *		struct tm *gmtime(t)
 *
 *	from time_t, make struct tm *
 *	
 **************************************************/

struct tm *gmtime(time_t *t)
{
	time_t curr;

	static struct tm gmtm;			/* for gmtime() */
	long day,sec,day0,day1;
	int year,month;

	if (t == NULL) {
		curr = time(NULL);
		t = &curr;
	}

	day = *t / 86400;			/* calc day from 1970.1.1 */
	sec = *t % 86400;			/* rest */
	gmtm.tm_hour = sec / 3600;		/* calc hour */
	sec = sec % 3600;			/* rest */
	gmtm.tm_min = sec / 60;			/* calc minitue */
	gmtm.tm_sec = sec % 60;			/* rest is second */
	gmtm.tm_wday = (day+4)%7;		/* calc day of week */
	year = day/365+70;			/* tmp year from 1900 */
	day0 = year2day(year);			/* calc day in year.1.1 */
	if (day0 > day)				/* check */
	    {
		year--;				/* if bad, re-calc day */
		day0 = year2day(year);
	    }
	gmtm.tm_year = year;			/* set year */
	day = day - day0;			/* calc day of year */
	gmtm.tm_yday = day;			/* set day of year */
	month = day / 29;			/* tmp month */
	day1 = mon2day(year,month);		/* calc day in year.month.1 */
	if (day1 > day)				/* check */
	    {
		month--;			/* if bad, re-calc */
		day1 = mon2day(year,month);	
	    }
	gmtm.tm_mon = month;
	day = day - day1;			/* calc day of month */
	gmtm.tm_mday = day +1 ;			/* set day */
	gmtm.tm_isdst = 0;			/* no support local time */
	return(&gmtm);
}
